//
// Created by cuichao on 2023/3/6.
//
#include <memory>
#include <modbus/modbus.h>
#include <cstring>

static modbus_t *client = nullptr;

#define START_ADDR 5

bool create_modbus_client(const char *port_name, int baudrate) {
    if (client != nullptr) {
        return true;
    }
    client = modbus_new_rtu(port_name, baudrate, 'N', 8, 1);
    if (-1 == modbus_connect(client)) {
        modbus_free(client);
        client = nullptr;
        fprintf(stderr, "连接串口错误: %s\n", modbus_strerror(errno));
        return false;
    }
    modbus_set_error_recovery(client, modbus_error_recovery_mode::MODBUS_ERROR_RECOVERY_PROTOCOL);
    return true;
}

bool set_slave(int slave_id) {
    if (client != nullptr) {
        return modbus_set_slave(client, slave_id) == 0;
    }
    return false;
}

bool read_detector(int detector_address, int detector_count, float *values, char *const errmsg) {

    if (detector_count <= 0 || detector_address <= 0) {
        const char *err = "节点地址和读取长度必须大于零";
        strcpy(errmsg, err);
        return false;
    }
    int register_addr = START_ADDR + (detector_address - 1) * 2;
    int read_register_count = detector_count * 2;

    std::unique_ptr<uint16_t[]> data = std::make_unique<uint16_t[]>(read_register_count);

    printf("real_addr:%d read_register_count:%d\n", register_addr, read_register_count);
    int ret = modbus_read_registers(client, register_addr, read_register_count, data.get());
    if (ret == -1) {
        fprintf(stderr, "读取错误: %s\n", modbus_strerror(errno));
        const char *err = "读取探测器数据异常";
        strcpy(errmsg, err);
        return false;
    }
    if (ret % 2 != 0) {
        const char *err = "返回值的数量不是偶数";
        strcpy(errmsg, err);
        return false;
    }
    uint16_t temp[2] = {0};
    for (int i = 0; i < ret; i += 2) {
        temp[0] = data[i + 1];
        temp[1] = data[i];
        float value = *((float *) temp);
        *values = value;
        values++;
    }

    return ret / 2;

}

void stop_modbus() {
    if (client != nullptr) {
        modbus_close(client);
        modbus_free(client);
        client = nullptr;
    }
}